#include "Decoder.h"




Decoder::Decoder() {
}

Message* Decoder::parser(std::string& receive) {
	char identify[1];
	identify[0] = receive.at(0);
	char tamanio[AMOUNT_BYTES_LONG];
	for (unsigned int i = 0; i < AMOUNT_BYTES_LONG; i++) {
		tamanio[i] = receive.at(i + 1);
	}

	uint8_t id_touint[1];
	memcpy(id_touint, identify, sizeof(uint8_t));
	unsigned int id = (unsigned int) *id_touint;

	uint32_t length_aux[AMOUNT_BYTES_LONG];
	memcpy(length_aux, tamanio, sizeof(uint32_t));
    this->id_msg=id;
	switch (id) {

	case 0:
	 return this->register_to_server(receive);
		break;
	case 1:
		return (new LoggingOk());
		break;
	case 2:
		return (new LoggingError());
		break;
	case 3:
		return (new GetFilesList());
		break;
	case 4:
		return (new NoFiles());
	case 5:
		return this->receive_list(receive);
		break;
	case 6:
		return this->get_file(receive);
		break;
	case 7:
		return this->file_not_found(receive);

	case 9:
		return this->put(receive);
		break;
	case 10:
		return this->putOk(receive);
		break;
	case 11:
		return this->putError(receive);
		break;
	case 12:
		return this->notify(receive);
		break;
	case 13:
		return (new Unregister());
		break;
	case 14:
		return (new MaxLoginTries());
       break;
	case 15:
	   return this->delete_file(receive);
	   break;
	case 16:
	   return this->deleteOk(receive);
	   break;
	case 17:
	  return this->deleteError(receive);
	  break;
	}
	return NULL;
}

FilesList* Decoder::receive_list(std::string& receive) {
	unsigned int begin = AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY;
	char field[100];
	int index_field = 0;
	File_Name name;
	Hash hash;
	char pivote;
	std::map<File_Name, Hash> mapFiles;
	bool in_hash = false; // indica q esta parseando el hash
	while (begin < receive.size()) {
		pivote = receive.at(begin);
		if ((pivote != '/') and (pivote != ' ')) {
			field[index_field] = receive.at(begin);
			index_field++;
		} else if (pivote == '/') {
			if (receive.at(begin + 1) == '/') {
				field[index_field] = '\0';
				name = std::string(field);
				begin++;
				index_field = 0;
				in_hash = true;
			} else {
				field[index_field] = receive.at(begin);
				index_field++;
			}
		}
		if (pivote == ' ' or begin == receive.size() - 1) {
			if (in_hash) {
				field[index_field] = '\0';
				hash = std::string(field);
				mapFiles.insert(std::pair<File_Name, Hash>(name, hash));
				index_field = 0;

				in_hash = false;
			} else {
				field[index_field] = receive.at(begin);
				index_field++;
			}

		}
		begin++;
	}

	FilesList *message = new FilesList(mapFiles);
	return message;
}


Register* Decoder::register_to_server(std::string& receive) {
	unsigned int index_receive = AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY;
	char c = receive.at(index_receive);
	int index = 0;
	char user[MAX_TAM_CAMPO];
	char pass[MAX_TAM_CAMPO];
	while (c != ' ') {
		user[index] = c;
		index++;
		index_receive++;
		c = receive.at(index_receive);
	}
	user[index] = '\0';
	index_receive++;
	index = 0;
	while (index_receive < receive.size()) {
		pass[index] = receive.at(index_receive);
		index++;
		index_receive++;
	}
	pass[index] = '\0';
	std::stringstream ss_user;
	std::string user_string;
	ss_user << user;
    ss_user >> user_string;

    std::stringstream ss_pass;
	std::string pass_string;
	ss_pass << pass;
	ss_pass >> pass_string;

	Register *message = new Register(&user_string, &pass_string);
    return message;
}

std::string Decoder::get_file_name(std::string& receive) {
	unsigned int index_receive = AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY;
	char file[100];
	int index = 0;
	std::string file_name= receive.substr(index_receive,receive.size()-1);
	return file_name;
}

GetFile* Decoder::get_file(std::string& receive) {
	std::string file_name = get_file_name(receive);
	GetFile *message = new GetFile(&file_name);
	return message;
}

FileNotFound* Decoder::file_not_found(std::string& receive){
	std::string file_name = get_file_name(receive);
	FileNotFound *message = new FileNotFound(&file_name);
	return message;
}

PutFile* Decoder::put(std::string& receive) {
	unsigned int index_receive = AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY;
	char name_file[100];
	char* file = new char[receive.size()
			- (AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY)+1];
	file[receive.size() - (AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY)]=0;
	char hash[100];
	int index = 0;
	char c = receive.at(index_receive);
	bool in_name = true;
	unsigned int pos = receive.find("//");
	std::string s_name_file = receive.substr(index_receive,
			pos - index_receive);

	index_receive = pos + 2;
	c = receive.at(index_receive);
	index = 0;
	while (c != ' ') {
		hash[index] = c;
		index++;
		index_receive++;
		c = receive.at(index_receive);
	}
	hash[index] = '\0';
	index_receive++;
	index = 0;
	while (index_receive < receive.size()) {
		file[index] = receive.at(index_receive);
		index++;
		index_receive++;
	}
    file[index] = '\0';

	std::stringstream ss_hash;
	std::string s_hash;
	ss_hash << hash;
	ss_hash >> s_hash;

	std::stringstream ss_file;
	std::string s_file;
	ss_file << file;
	ss_file >> s_file;

	PutFile *message = new PutFile(&s_name_file, &s_hash, &s_file);

	delete[] file;
	return message;
}

PutOk * Decoder::putOk(std::string& receive){
	std::string file_name = get_file_name(receive);
	PutOk *message = new PutOk(&file_name);
	return message;
}

PutError * Decoder::putError(std::string& receive){
	std::string file_name = get_file_name(receive);
	PutError *message = new PutError(&file_name);
	return message;
}

Notify* Decoder::notify(std::string& receive) {
	unsigned int index_receive = AMOUNT_BYTES_LONG + AMOUNT_BYTES_IDENTIFY;
	char abm = receive.at(index_receive);
	index_receive++;
	std::string s_name_file = receive.substr(index_receive,receive.size() -1);

	Notify *message = new Notify(&s_name_file,abm);
	return message;
}

Delete* Decoder::delete_file(std::string& receive){
	std::string file_name = get_file_name(receive);
	Delete *message = new Delete(&file_name);
	return message;
}


DeleteOk* Decoder::deleteOk(std::string& receive){
	std::string file_name = get_file_name(receive);
	DeleteOk *message = new DeleteOk(&file_name);
	return message;
}

DeleteError* Decoder::deleteError(std::string& receive){
	std::string file_name = get_file_name(receive);
	DeleteError *message = new DeleteError(&file_name);
	return message;
}
int Decoder::get_id_msg(){
	return this->id_msg;
}
Decoder::~Decoder() {
}
